package com.wxscrmplus.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.base.Joiner;
import com.wxscrmplus.common.core.domain.entity.SysUser;
import com.wxscrmplus.common.core.service.UserService;
import com.wxscrmplus.common.exception.ServiceException;
import com.wxscrmplus.common.helper.LoginHelper;
import com.wxscrmplus.common.utils.DateUtils;
import com.wxscrmplus.common.utils.StreamUtils;
import com.wxscrmplus.common.utils.StringUtils;
import com.wxscrmplus.common.core.page.TableDataInfo;
import com.wxscrmplus.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wxscrmplus.common.utils.spring.SpringUtils;
import com.wxscrmplus.customer.domain.FollowUser;
import com.wxscrmplus.customer.domain.CustomerLog;
import com.wxscrmplus.customer.domain.bo.CustomerTransferBo;
import com.wxscrmplus.customer.domain.feat.CustomerFeat;
import com.wxscrmplus.customer.domain.vo.CusTypeVo;
import com.wxscrmplus.customer.domain.vo.FollowUserVo;
import com.wxscrmplus.customer.mapper.*;
import com.wxscrmplus.customer.mapper.CusTypeMapper;
import com.wxscrmplus.customer.mapper.CustomerLogMapper;
import com.wxscrmplus.customer.mapper.CustomerMapper;
import com.wxscrmplus.customer.mapper.FollowUserMapper;
import com.wxscrmplus.devtool.service.IDevConfigService;
import com.wxscrmplus.drainage.domain.vo.DraChannelVo;
import com.wxscrmplus.drainage.domain.vo.DraQrcodeVo;
import com.wxscrmplus.drainage.mapper.DraChannelMapper;
import com.wxscrmplus.drainage.mapper.DraQrcodeMapper;
import com.wxscrmplus.drainage.service.IDraQrcodeService;
import com.wxscrmplus.marketing.service.IMarWelcomeMessageService;
import com.wxscrmplus.riskcontrol.domain.RiskDeleteFriend;
import com.wxscrmplus.riskcontrol.mapper.RiskDeleteFriendMapper;
import com.wxscrmplus.statistics.service.IChannelStatsService;
import com.wxscrmplus.statistics.service.ICustomerStatsService;
import com.wxscrmplus.system.domain.SysOss;
import com.wxscrmplus.system.domain.vo.SysOssVo;
import com.wxscrmplus.system.mapper.SysUserMapper;
import com.wxscrmplus.system.service.ISysOssService;
import com.wxscrmplus.wxcp.factory.WxCpServiceFactory;
import com.wxscrmplus.customer.domain.Customer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import org.springframework.stereotype.Service;
import com.wxscrmplus.customer.domain.bo.CustomerBo;
import com.wxscrmplus.customer.domain.vo.CustomerVo;
import com.wxscrmplus.customer.service.ICustomerService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 客户Service业务层处理
 *
 * @author 王永超
 * @date 2023-03-24
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class CustomerServiceImpl extends WxCpServiceFactory implements ICustomerService {

    private final CustomerMapper baseMapper;
    private final CusTypeMapper typeMapper;
    private final FollowUserMapper followUserMapper;
    private final SysUserMapper userMapper;
    private final DraQrcodeMapper qrcodeMapper;
    private final IDraQrcodeService qrcodeService;
    private final ISysOssService ossService;
    private final DraChannelMapper channelMapper;
    private final ICustomerStatsService customerStatsService;
    private final UserService userService;
    private final IChannelStatsService channelStatsService;
    private final RiskDeleteFriendMapper deleteFriendMapper;
    private final CustomerLogMapper customerLogMapper;
    private final IMarWelcomeMessageService welcomeMessageService;


    /**
     * 查询客户
     */
    @Override
    public CustomerVo queryById(Long customerId) {
        customerStatsService.refreshCostsByCustomerIds(customerId);
        CustomerVo customerVo = baseMapper.selectVoById(customerId);
        if (ObjectUtil.isNotEmpty(customerVo.getCusTypeId())) {
            CusTypeVo cusTypeVo = typeMapper.selectVoById(customerVo.getCusTypeId());
            if (ObjectUtil.isNotNull(cusTypeVo)) {
                customerVo.setCusTypeName(cusTypeVo.getName());
            }
        }
        customerVo.setTodayOpportunityAmount(customerStatsService.getTodayOpportunityAmount(customerId));
        customerVo.setAvatarUrl(ossService.genOssUrl(customerVo.getAvatar(), 10));
        CustomerFeat customerFeat = BeanUtil.toBean(customerVo, CustomerFeat.class);
        customerFeat.calculatProfit();
        customerVo.setProfit(customerFeat.getProfit());
        return customerVo;
    }

    /**
     * 查询客户列表
     */
    @Override
    public TableDataInfo<CustomerVo> queryPageList(CustomerBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Customer> lqw = buildQueryWrapper(bo);
        Page<CustomerVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        for (CustomerVo customerVo : result.getRecords()) {
            CusTypeVo cusTypeVo = typeMapper.selectVoById(customerVo.getCusTypeId());
            if (ObjectUtil.isNotNull(cusTypeVo)) {
                customerVo.setCusTypeName(cusTypeVo.getName());
            }
            customerVo.setAvatarUrl(ossService.genOssUrl(customerVo.getAvatar(), 10));
            List<FollowUserVo> followUserVoList = followUserMapper.selectVoList(Wrappers.query(new FollowUser()).lambda().eq(FollowUser::getCustomerId, customerVo.getCustomerId()));
            List<Long> userIds = StreamUtils.toList(followUserVoList, FollowUserVo::getUserId);
            List<SysUser> sysUserList = userMapper.findBatchIds(userIds);
            customerVo.setFollowUserNickNames(Joiner.on(",").join(StreamUtils.toList(sysUserList, SysUser::getNickName)));
            Map<Long, String> userNameMap = StreamUtils.toMap(sysUserList, SysUser::getUserId, SysUser::getNickName);
            for (FollowUserVo followUserVo : followUserVoList) {
                followUserVo.setUserNickName(userNameMap.get(followUserVo.getUserId()));
                DraChannelVo draChannelVo = channelMapper.selectVoById(followUserVo.getChannelId());
                if (ObjectUtil.isNotNull(draChannelVo)) {
                    followUserVo.setChannelName(draChannelVo.getName());
                }
            }
            customerVo.setTodayOpportunityAmount(customerStatsService.getTodayOpportunityAmount(customerVo.getCustomerId()));
            customerVo.setFollowUsers(followUserVoList);
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询客户列表
     */
    @Override
    public List<CustomerVo> queryList(CustomerBo bo) {
        LambdaQueryWrapper<Customer> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Customer> buildQueryWrapper(CustomerBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<Customer> wrapper = Wrappers.query();
        wrapper.lambda().like(StringUtils.isNotBlank(bo.getName()), Customer::getName, bo.getName());
        wrapper.lambda().eq(StringUtils.isNotBlank(bo.getGender()), Customer::getGender, bo.getGender());
        wrapper.lambda().eq(StringUtils.isNotBlank(bo.getEntryType()), Customer::getEntryType, bo.getEntryType());
        wrapper.lambda().eq(StringUtils.isNotBlank(bo.getFollowStage()), Customer::getFollowStage, bo.getFollowStage());
        wrapper.lambda().eq(bo.getCusTypeId() != null, Customer::getCusTypeId, bo.getCusTypeId());
        List<Long> dataRangeUserIds = bo.getDataRangeUserIds();
        if (CollUtil.isEmpty(dataRangeUserIds)) {
            dataRangeUserIds = Collections.singletonList(-1L);
        }
        String delType = Joiner.on(",").join(Arrays.asList(FollowUser.DelTypeFieldEnums.ZERO.getValue(), FollowUser.DelTypeFieldEnums.ONE.getValue()));
        wrapper.inSql("customer_id", String.format("SELECT customer_id FROM `cus_follow_user` WHERE del_type IN(%s) AND user_id in(%s)",
            delType, Joiner.on(",").join(dataRangeUserIds)));
        wrapper.lambda().orderByDesc(Customer::getCustomerId);
        return wrapper.lambda();
    }

    /**
     * 新增客户
     */
    @Override
    public Boolean insertByBo(CustomerBo bo) {
        Customer add = BeanUtil.toBean(bo, Customer.class);
        validEntityBeforeSave(add);
        add.setOpportunityAmount(BigDecimal.ZERO);
        add.setMaintainCost(BigDecimal.ZERO);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCustomerId(add.getCustomerId());
        }
        FollowUser followUser = new FollowUser();
        followUser.setDelType(FollowUser.DelTypeFieldEnums.ZERO.getValue());
        followUser.setCustomerId(add.getCustomerId());
        followUser.setUserId(LoginHelper.getUserId());
        followUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
        followUser.setFollowStage(bo.getFollowStage());
        followUserMapper.insert(followUser);
        CustomerLog customerLog = new CustomerLog();
        customerLog.setCustomerId(add.getCustomerId());
        customerLog.setAbstractText("客户入库");
        customerLogMapper.insert(customerLog);
        return flag;
    }

    /**
     * 修改客户
     */
    @Override
    public Boolean updateByBo(CustomerBo bo) {
        Customer update = BeanUtil.toBean(bo, Customer.class);
        validEntityBeforeSave(update);
        baseMapper.update(null, new UpdateWrapper<Customer>()
            .lambda()
            .set(Customer::getAvatar, update.getAvatar())
            .eq(Customer::getCustomerId, update.getCustomerId()));
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Customer entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除客户
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //删除系统客户，把客户流入公海（客户没有跟进人的是公海数据）
        FollowUser followUser = new FollowUser();
        followUser.setDelType(FollowUser.DelTypeFieldEnums.TWO.getValue());
        followUser.setUserDelTime(new Date());
        List<RiskDeleteFriend> addRiskDeleteFriends = new ArrayList<>();
        for (Long id : ids) {
            RiskDeleteFriend riskDeleteFriend = new RiskDeleteFriend();
            riskDeleteFriend.setCustomerId(id);
            riskDeleteFriend.setUserId(LoginHelper.getUserId());
            riskDeleteFriend.setDelType(RiskDeleteFriend.DelTypeFieldEnums.YUANGONGSHANCHU.getValue());
            addRiskDeleteFriends.add(riskDeleteFriend);
        }
        if (!deleteFriendMapper.insertBatch(addRiskDeleteFriends) || followUserMapper.update(followUser, Wrappers.query(new FollowUser()).lambda().in(FollowUser::getCustomerId, ids)) == 0) {
            throw new ServiceException("系统异常");
        }
        List<Customer> customerList = baseMapper.selectBatchIds(ids);
        String remindConfig = SpringUtils.getBean(IDevConfigService.class).selectConfigByKey("delete.friend.remind.config");
        JSONObject remindConfigJson = JSONUtil.toBean(remindConfig, JSONObject.class);
        boolean deleteCustomerRemind = Boolean.parseBoolean(remindConfigJson.getStr("deleteCustomer"));
        if (deleteCustomerRemind) {
            List<Long> receiveUserIds = remindConfigJson.getBeanList("receiveUserIds", Long.class);
            List<SysUser> receiveUserList = userMapper.selectVoBatchIds(receiveUserIds);
            for (SysUser sysUser : receiveUserList) {
                sendDeleteFriendRemindMessage(sysUser, RiskDeleteFriend.DelTypeFieldEnums.YUANGONGSHANCHU, "跟进人删除客户，如有疑惑请前往了解情况！", customerList, userMapper.selectUserById(LoginHelper.getUserId()));
            }
        }
        return true;
    }

    /**
     * 添加客户事件业务处理
     *
     * @param allFieldsMap
     */
    @Lock4j(name = WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT, expire = 60000, acquireTimeout = 1000)
    @Override
    public void addExternalContactHandle(Map<String, Object> allFieldsMap) {
        String userID = allFieldsMap.get("UserID").toString();
        SysUser targetUser = userMapper.selectUserByUserName(userID);
        String externalUserID = allFieldsMap.get("ExternalUserID").toString();
        String welcomeCode = allFieldsMap.get("WelcomeCode").toString();
        //客户信息
        WxCpExternalContactInfo externalContactInfo = null;
        try {
            externalContactInfo = getExternalContactService().getExternalContact(externalUserID);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        ExternalContact externalContact = externalContactInfo.getExternalContact();
        Customer customer = baseMapper.selectOne(Wrappers.query(new Customer()).lambda().eq(Customer::getQwExternalUserid, externalUserID));
        String relType = FollowUser.RelTypeFieldEnums.TWO.getValue();
        if (ObjectUtil.isNull(customer)) {
            //客户不在系统中说明是最先添加的，设置为跟进人关系
            relType = FollowUser.RelTypeFieldEnums.ONE.getValue();
            SysOssVo sysOssVo = null;
            try {
                sysOssVo = ossService.upload(externalContact.getAvatar(), SysOss.DownloadFieldEnum.LOGIN.getValue());
            } catch (Exception e) {
                sysOssVo = new SysOssVo();
            }//录入系统
            customer = new Customer();
            customer.setQwExternalUserid(externalContact.getExternalUserId());
            customer.setName(externalContact.getName());
            customer.setPositionName(externalContact.getPosition());
            customer.setAvatar(sysOssVo.getOssId());
            customer.setCorpName(externalContact.getCorpName());
            customer.setCorpFullName(externalContact.getCorpFullName());
            customer.setType(String.valueOf(externalContact.getType()));
            customer.setGender(String.valueOf(externalContact.getGender()));
            customer.setQwUnionid(externalContact.getUnionId());
            customer.setEntryType(Customer.EntryTypeFieldEnums.ONE.getValue());
            customer.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
            customer.setOpportunityAmount(BigDecimal.ZERO);
            customer.setMaintainCost(BigDecimal.ZERO);
            baseMapper.insert(customer);
            CustomerLog customerLog = new CustomerLog();
            customerLog.setCustomerId(customer.getCustomerId());
            customerLog.setAbstractText("客户入库");
            customerLogMapper.insert(customerLog);
        }
        List<FollowedUser> followedUsers = externalContactInfo.getFollowedUsers();
        followedUsers.stream().sorted(Comparator.comparing(FollowedUser::getCreateTime)).collect(Collectors.toList());
        for (int i = 0; i < followedUsers.size(); i++) {
            FollowedUser qwFollowedUser = followedUsers.get(i);
            SysUser user = userMapper.selectUserByUserName(qwFollowedUser.getUserId());
            if (ObjectUtil.isNull(user)) {
                log.info("该成员不在系统：{}", qwFollowedUser.getUserId());
                continue;
            }
            FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
                .eq(FollowUser::getCustomerId, customer.getCustomerId())
                .eq(FollowUser::getUserId, user.getUserId()));
            if (ObjectUtil.isNull(followUser)) {
                followUser = new FollowUser();
                followUser.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
                followUser.setCustomerId(customer.getCustomerId());
                followUser.setUserId(user.getUserId());
                followUser.setWinCost(BigDecimal.ZERO);
            }
            if (userID.equals(qwFollowedUser.getUserId())) {
                followUser.setRelType(relType);
                followUser.setDelType(FollowUser.DelTypeFieldEnums.ZERO.getValue());
            }
            followUser.setQwCreatetime(DateUtils.toDate(LocalDateTimeUtil.of(qwFollowedUser.getCreateTime())));
            followUser.setRemark(qwFollowedUser.getRemark());
            followUser.setDescription(qwFollowedUser.getDescription());
            followUser.setQwAddWay(qwFollowedUser.getAddWay());
            followUser.setRemarkCorpName(qwFollowedUser.getRemarkCorpName());
            followUser.setRemarkMobiles(Arrays.asList(qwFollowedUser.getRemarkMobiles()));
            followUser.setQwOperUserid(qwFollowedUser.getOperatorUserId());
            followUser.setRemark(qwFollowedUser.getRemark());
            followUserMapper.insertOrUpdate(followUser);
        }
        //分析客户来源&发送欢迎语
        if (ObjectUtil.isNotNull(allFieldsMap.get("State"))) {
            List<String> stateList = Arrays.asList((String.valueOf(allFieldsMap.get("State").toString())).split(":"));
            if (stateList.get(0).equals("1")) {
                //渠道活码ID
                Long qrcodeId = Long.parseLong(stateList.get(1));
                DraQrcodeVo qrcodeVo = qrcodeMapper.selectVoById(qrcodeId);
                if (ObjectUtil.isNotNull(qrcodeVo.getIsSendWelcome()) && qrcodeVo.getIsSendWelcome() &&
                    ObjectUtil.isNotNull(qrcodeVo.getWelcomeMsgId())) {
                    //发送欢迎语
                    welcomeMessageService.send(qrcodeVo.getWelcomeMsgId(), welcomeCode);
                }
                DraChannelVo draChannelVo = channelMapper.selectVoById(qrcodeVo.getChannelId());
                FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
                    .eq(FollowUser::getCustomerId, customer.getCustomerId())
                    .eq(FollowUser::getUserId, targetUser.getUserId()));
                followUser.setChannelId(qrcodeVo.getChannelId());
                followUser.setQrcodeId(qrcodeVo.getQrcodeId());
                followUser.setQrcodeTableType(Integer.parseInt(stateList.get(0)));
                followUser.setWinCost(draChannelVo.getCost());
                followUserMapper.updateById(followUser);
                channelStatsService.refreshTotalCustomer(qrcodeVo.getChannelId());
                customerStatsService.refreshCostsByCustomerIds(customer.getCustomerId());
                //更新渠道活码添加客户上限
                qrcodeService.refreshQrcodeUser(qrcodeMapper.selectById(qrcodeId));
            }
        }

    }

    /**
     * 编辑客户事件业务处理
     *
     * @param allFieldsMap
     */
    @Lock4j(name = WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT, expire = 60000, acquireTimeout = 1000)
    @Override
    public void editExternalContactHandle(Map<String, Object> allFieldsMap) {
        String userID = allFieldsMap.get("UserID").toString();
        String externalUserID = allFieldsMap.get("ExternalUserID").toString();
        //客户信息
        WxCpExternalContactInfo externalContactInfo = null;
        try {
            externalContactInfo = getExternalContactService().getExternalContact(externalUserID);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        ExternalContact externalContact = externalContactInfo.getExternalContact();
        SysOssVo sysOssVo = null;
        try {
            sysOssVo = ossService.upload(externalContact.getAvatar(), SysOss.DownloadFieldEnum.LOGIN.getValue());
        } catch (Exception e) {
            sysOssVo = new SysOssVo();
        }
        Customer customer = baseMapper.selectOne(Wrappers.query(new Customer()).lambda().eq(Customer::getQwExternalUserid, externalUserID));
        String relType = FollowUser.RelTypeFieldEnums.TWO.getValue();
        if (ObjectUtil.isNull(customer)) {
            //客户不在系统中说明是最先添加的，设置为跟进人关系
            relType = FollowUser.RelTypeFieldEnums.ONE.getValue();
            //录入系统
            customer = new Customer();
            customer.setQwExternalUserid(externalContact.getExternalUserId());
            customer.setName(externalContact.getName());
            customer.setPositionName(externalContact.getPosition());
            customer.setAvatar(sysOssVo.getOssId());
            customer.setCorpName(externalContact.getCorpName());
            customer.setCorpFullName(externalContact.getCorpFullName());
            customer.setType(String.valueOf(externalContact.getType()));
            customer.setGender(String.valueOf(externalContact.getGender()));
            customer.setQwUnionid(externalContact.getUnionId());
            customer.setEntryType(Customer.EntryTypeFieldEnums.ONE.getValue());
            customer.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
            customer.setOpportunityAmount(BigDecimal.ZERO);
            customer.setMaintainCost(BigDecimal.ZERO);
            baseMapper.insert(customer);
        } else {
            Customer update = new Customer();
            update.setCustomerId(customer.getCustomerId());
            update.setAvatar(sysOssVo.getOssId());
            baseMapper.updateById(update);
        }
        List<FollowedUser> followedUsers = externalContactInfo.getFollowedUsers();
        followedUsers.stream().sorted(Comparator.comparing(FollowedUser::getCreateTime)).collect(Collectors.toList());
        for (int i = 0; i < followedUsers.size(); i++) {
            FollowedUser qwFollowedUser = followedUsers.get(i);
            SysUser user = userMapper.selectUserByUserName(qwFollowedUser.getUserId());
            if (ObjectUtil.isNull(user)) {
                log.info("该成员不在系统：{}", qwFollowedUser.getUserId());
                continue;
            }
            FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
                .eq(FollowUser::getCustomerId, customer.getCustomerId())
                .eq(FollowUser::getUserId, user.getUserId()));
            if (ObjectUtil.isNull(followUser)) {
                followUser = new FollowUser();
                followUser.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
                followUser.setCustomerId(customer.getCustomerId());
                followUser.setUserId(user.getUserId());
                if (userID.equals(qwFollowedUser.getUserId())) {
                    followUser.setRelType(relType);
                    followUser.setDelType(FollowUser.DelTypeFieldEnums.ZERO.getValue());
                }
            }
            followUser.setQwCreatetime(DateUtils.toDate(LocalDateTimeUtil.of(qwFollowedUser.getCreateTime())));
            followUser.setRemark(qwFollowedUser.getRemark());
            followUser.setDescription(qwFollowedUser.getDescription());
            followUser.setQwAddWay(qwFollowedUser.getAddWay());
            followUser.setRemarkCorpName(qwFollowedUser.getRemarkCorpName());
            followUser.setRemarkMobiles(Arrays.asList(qwFollowedUser.getRemarkMobiles()));
            followUser.setQwOperUserid(qwFollowedUser.getOperatorUserId());
            followUser.setRemark(qwFollowedUser.getRemark());
            followUserMapper.insertOrUpdate(followUser);
        }

    }

    /**
     * 员工删除客户事件业务处理
     *
     * @param allFieldsMap
     */
    @Lock4j(name = WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT, expire = 60000, acquireTimeout = 1000)
    @Override
    public void delExternalExternalContactHandle(Map<String, Object> allFieldsMap) {
        String userID = allFieldsMap.get("UserID").toString();
        String externalUserID = allFieldsMap.get("ExternalUserID").toString();
        SysUser user = userMapper.selectUserByUserName(userID);
        if (ObjectUtil.isNull(user)) {
            log.info("该成员不在系统：{}", userID);
            throw new ServiceException("该成员不在系统：{}" + userID);
        }
        Customer customer = baseMapper.selectOne(Wrappers.query(new Customer()).lambda().eq(Customer::getQwExternalUserid, externalUserID));
        FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
            .eq(FollowUser::getCustomerId, customer.getCustomerId())
            .eq(FollowUser::getUserId, user.getUserId()));
        if (followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.TWO.getValue())) {
            return;
        }
        FollowUser update = new FollowUser();
        update.setFollowId(followUser.getFollowId());
        if (followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.ONE.getValue()) ||
            followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.THREE.getValue())) {
            //客户已经删除员工，现在员工删除客户，就是双向删除
            update.setDelType(FollowUser.DelTypeFieldEnums.THREE.getValue());
        } else {
            update.setDelType(FollowUser.DelTypeFieldEnums.TWO.getValue());
        }
        //删除后必须设置为共享人关系（后设置其他人为跟进人）
        update.setRelType(FollowUser.RelTypeFieldEnums.TWO.getValue());
        update.setUserDelTime(new Date());
        followUserMapper.updateById(update);
        Long count = followUserMapper.selectCount(Wrappers.query(new FollowUser()).lambda()
            .eq(FollowUser::getRelType, FollowUser.RelTypeFieldEnums.ONE.getValue())
            .eq(FollowUser::getCustomerId, customer.getCustomerId())
            .in(FollowUser::getDelType, FollowUser.DelTypeFieldEnums.ONE.getValue(), FollowUser.DelTypeFieldEnums.ZERO.getValue()));
        if (count < 1) {
            //是否没有跟进人（是否把跟当前进人设置为共享人了），没有需要变更客户的主跟进人
            List<FollowUser> followUserList = followUserMapper.selectList(Wrappers.query(new FollowUser()).lambda()
                .eq(FollowUser::getCustomerId, customer.getCustomerId())
// 489f219c3f1430059d8ce9ffd787ab01
                .in(FollowUser::getDelType, FollowUser.DelTypeFieldEnums.ONE.getValue(), FollowUser.DelTypeFieldEnums.ZERO.getValue())
                .orderByAsc(FollowUser::getQwCreatetime));
            if (CollUtil.isNotEmpty(followUserList)) {
                //设置最新添加的为跟进人
                FollowUser shareFollowUser = followUserList.get(0);
                shareFollowUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
                followUserMapper.updateById(shareFollowUser);
                CustomerLog customerLog = new CustomerLog();
                customerLog.setCustomerId(customer.getCustomerId());
                customerLog.setAbstractText(String.format("%s 将客户 %s 转让给 %s", user.getNickName(), customer.getName(), userMapper.findNickNameById(shareFollowUser.getUserId())));
                customerLogMapper.insert(customerLog);
                sendTransferCustomerMessage(user, userService.selectUserNameById(shareFollowUser.getUserId()), Collections.singletonList(customer));
            }
        }
        //新增删除记录&提醒通知
        RiskDeleteFriend riskDeleteFriend = new RiskDeleteFriend();
        riskDeleteFriend.setCustomerId(customer.getCustomerId());
        riskDeleteFriend.setUserId(user.getUserId());
        riskDeleteFriend.setDelType(RiskDeleteFriend.DelTypeFieldEnums.YUANGONGSHANCHU.getValue());
        deleteFriendMapper.insert(riskDeleteFriend);
        String remindConfig = SpringUtils.getBean(IDevConfigService.class).selectConfigByKey("delete.friend.remind.config");
        JSONObject remindConfigJson = JSONUtil.toBean(remindConfig, JSONObject.class);
        boolean deleteCustomerRemind = Boolean.parseBoolean(remindConfigJson.getStr("deleteCustomer"));
        if (deleteCustomerRemind) {
            List<Long> receiveUserIds = remindConfigJson.getBeanList("receiveUserIds", Long.class);
            List<SysUser> receiveUserList = userMapper.selectVoBatchIds(receiveUserIds);
            for (SysUser sysUser : receiveUserList) {
                sendDeleteFriendRemindMessage(sysUser, RiskDeleteFriend.DelTypeFieldEnums.YUANGONGSHANCHU, "跟进人删除客户，如有疑惑请前往了解情况！", Collections.singletonList(customer), user);
            }
        }
    }

    /**
     * 客户删除员工事件业务处理
     *
     * @param allFieldsMap
     */
    @Lock4j(name = WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT, expire = 60000, acquireTimeout = 1000)
    @Override
    public void delFollowExternalContactHandle(Map<String, Object> allFieldsMap) {
        String userID = allFieldsMap.get("UserID").toString();
        String externalUserID = allFieldsMap.get("ExternalUserID").toString();
        SysUser user = userMapper.selectUserByUserName(userID);
        if (ObjectUtil.isNull(user)) {
            log.info("该成员不在系统：{}", userID);
            throw new ServiceException("该成员不在系统：{}" + userID);
        }
        Customer customer = baseMapper.selectOne(Wrappers.query(new Customer()).lambda().eq(Customer::getQwExternalUserid, externalUserID));
        sendDeleteFriendRemindMessage(user, RiskDeleteFriend.DelTypeFieldEnums.KEHUSHANCHU, "客户刚刚已把你从TA的好友列表中移除，如有疑惑请前往了解情况！", Collections.singletonList(customer), user);
        FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
            .eq(FollowUser::getCustomerId, customer.getCustomerId())
            .eq(FollowUser::getUserId, user.getUserId()));
        if (followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.ONE.getValue())) {
            return;
        }
        FollowUser update = new FollowUser();
        update.setFollowId(followUser.getFollowId());
        if (followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.TWO.getValue()) ||
            followUser.getDelType().equals(FollowUser.DelTypeFieldEnums.THREE.getValue())) {
            //员工已经删除客户，现在客户删除员工，就是双向删除
            update.setDelType(FollowUser.DelTypeFieldEnums.THREE.getValue());
        } else {
            update.setDelType(FollowUser.DelTypeFieldEnums.ONE.getValue());
        }
        update.setCustomerDelTime(new Date());
        String remindConfig = SpringUtils.getBean(IDevConfigService.class).selectConfigByKey("delete.friend.remind.config");
        JSONObject remindConfigJson = JSONUtil.toBean(remindConfig, JSONObject.class);
        boolean deleteUserRemind = Boolean.parseBoolean(remindConfigJson.getStr("deleteUser"));
        if (deleteUserRemind) {
            List<Long> receiveUserIds = remindConfigJson.getBeanList("receiveUserIds", Long.class);
            List<SysUser> receiveUserList = userMapper.selectVoBatchIds(receiveUserIds);
            for (SysUser sysUser : receiveUserList) {
                sendDeleteFriendRemindMessage(sysUser, RiskDeleteFriend.DelTypeFieldEnums.KEHUSHANCHU, "客户删除跟进人，如有疑惑请前往了解情况！", Collections.singletonList(customer), user);
            }
        }
        followUserMapper.updateById(update);
        RiskDeleteFriend riskDeleteFriend = new RiskDeleteFriend();
        riskDeleteFriend.setCustomerId(customer.getCustomerId());
        riskDeleteFriend.setUserId(user.getUserId());
        riskDeleteFriend.setDelType(RiskDeleteFriend.DelTypeFieldEnums.KEHUSHANCHU.getValue());
        deleteFriendMapper.insert(riskDeleteFriend);
    }


    /**
     * 同步企微客户
     */
    @Lock4j(name = "syncExternalContact", expire = 60000, acquireTimeout = 1000)
    @Override
    public void syncExternalContact() {
        List<String> qwUserIds = userService.getQwUserId();
        WxCpExternalContactService externalContactService = getExternalContactService();
        for (String userID : qwUserIds) {
            List<String> externalUserIds = null;
            try {
                externalUserIds = externalContactService.listExternalContacts(userID);
            } catch (WxErrorException e) {
                throw new RuntimeException(e);
            }
            for (String externalUserID : externalUserIds) {
                //客户信息
                WxCpExternalContactInfo externalContactInfo = null;
                try {
                    externalContactInfo = getExternalContactService().getExternalContact(externalUserID);
                } catch (WxErrorException e) {
                    throw new RuntimeException(e);
                }
                ExternalContact externalContact = externalContactInfo.getExternalContact();
                SysOssVo sysOssVo = null;
                try {
                    sysOssVo = ossService.upload(externalContact.getAvatar(), SysOss.DownloadFieldEnum.LOGIN.getValue());
                } catch (Exception e) {
                    sysOssVo = new SysOssVo();
                }
                Customer customer = baseMapper.selectOne(Wrappers.query(new Customer()).lambda().eq(Customer::getQwExternalUserid, externalUserID));
                boolean newCustomer = false;
                if (ObjectUtil.isNull(customer)) {
                    //客户不在系统中说明是最先添加的，设置为跟进人关系
                    newCustomer = true;
                    //录入系统
                    customer = new Customer();
                    customer.setQwExternalUserid(externalContact.getExternalUserId());
                    customer.setName(externalContact.getName());
                    customer.setPositionName(externalContact.getPosition());
                    customer.setAvatar(sysOssVo.getOssId());
                    customer.setCorpName(externalContact.getCorpName());
                    customer.setCorpFullName(externalContact.getCorpFullName());
                    customer.setType(String.valueOf(externalContact.getType()));
                    customer.setGender(String.valueOf(externalContact.getGender()));
                    customer.setQwUnionid(externalContact.getUnionId());
                    customer.setEntryType(Customer.EntryTypeFieldEnums.ONE.getValue());
                    customer.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
                    customer.setOpportunityAmount(BigDecimal.ZERO);
                    customer.setMaintainCost(BigDecimal.ZERO);
                    baseMapper.insert(customer);
                    CustomerLog customerLog = new CustomerLog();
                    customerLog.setCustomerId(customer.getCustomerId());
                    customerLog.setAbstractText("客户入库");
                    customerLogMapper.insert(customerLog);
                } else {
                    Customer updateCustomer = new Customer();
                    updateCustomer.setCustomerId(customer.getCustomerId());
                    updateCustomer.setQwExternalUserid(externalContact.getExternalUserId());
                    updateCustomer.setName(externalContact.getName());
                    updateCustomer.setPositionName(externalContact.getPosition());
                    updateCustomer.setAvatar(sysOssVo.getOssId());
                    updateCustomer.setCorpName(externalContact.getCorpName());
                    updateCustomer.setCorpFullName(externalContact.getCorpFullName());
                    updateCustomer.setType(String.valueOf(externalContact.getType()));
                    updateCustomer.setGender(String.valueOf(externalContact.getGender()));
                    updateCustomer.setQwUnionid(externalContact.getUnionId());
                    baseMapper.updateById(updateCustomer);
                }
                List<FollowedUser> followedUsers = externalContactInfo.getFollowedUsers();
                followedUsers.stream().sorted(Comparator.comparing(FollowedUser::getCreateTime)).collect(Collectors.toList());
                List<Long> userIds = new ArrayList<>();
                for (int i = 0; i < followedUsers.size(); i++) {
                    FollowedUser qwFollowedUser = followedUsers.get(i);
                    SysUser user = userMapper.selectUserByUserName(qwFollowedUser.getUserId());
                    if (ObjectUtil.isNull(user)) {
                        log.info("该成员不在系统：{}", qwFollowedUser.getUserId());
                        continue;
                    }
                    userIds.add(user.getUserId());
                    FollowUser followUser = followUserMapper.selectOne(Wrappers.query(new FollowUser()).lambda()
                        .eq(FollowUser::getCustomerId, customer.getCustomerId())
                        .eq(FollowUser::getUserId, user.getUserId()));
                    if (ObjectUtil.isNull(followUser)) {
                        followUser = new FollowUser();
                        followUser.setFollowStage(Customer.FollowStageFieldEnums.DAIGOUTONG.getValue());
                        followUser.setCustomerId(customer.getCustomerId());
                        followUser.setUserId(user.getUserId());
                        followUser.setDelType(FollowUser.DelTypeFieldEnums.ZERO.getValue());
                        if (newCustomer && i == 0) {
                            //客户不在系统中说明是最先添加的，设置为跟进人关系
                            followUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
                        } else {
                            followUser.setRelType(FollowUser.RelTypeFieldEnums.TWO.getValue());
                        }
                    }
                    followUser.setQwCreatetime(DateUtils.toDate(LocalDateTimeUtil.of(qwFollowedUser.getCreateTime())));
                    followUser.setRemark(qwFollowedUser.getRemark());
                    followUser.setDescription(qwFollowedUser.getDescription());
                    followUser.setQwAddWay(qwFollowedUser.getAddWay());
                    followUser.setRemarkCorpName(qwFollowedUser.getRemarkCorpName());
                    followUser.setRemarkMobiles(Arrays.asList(qwFollowedUser.getRemarkMobiles()));
                    followUser.setQwOperUserid(qwFollowedUser.getOperatorUserId());
                    followUser.setRemark(qwFollowedUser.getRemark());
                    String state = qwFollowedUser.getState();
                    //分析客户来源
                    if (ObjectUtil.isNull(followUser.getChannelId()) && ObjectUtil.isNotNull(state)) {
                        List<String> stateList = Arrays.asList((state).split(":"));
                        if (stateList.get(0).equals("1")) {
                            //渠道活码ID
                            Long qrcodeId = Long.parseLong(stateList.get(1));
                            DraQrcodeVo qrcodeVo = qrcodeMapper.selectVoById(qrcodeId);
                            if (ObjectUtil.isNotNull(qrcodeVo)) {
                                DraChannelVo draChannelVo = channelMapper.selectVoById(qrcodeVo.getChannelId());
                                if (ObjectUtil.isNotNull(draChannelVo)) {
                                    followUser.setChannelId(qrcodeVo.getChannelId());
                                    channelStatsService.refreshTotalCustomer(qrcodeVo.getChannelId());
                                }
                                followUser.setWinCost(draChannelVo.getCost());
                            }
                            followUser.setQrcodeId(qrcodeId);
                            followUser.setQrcodeTableType(Integer.parseInt(stateList.get(0)));
                        }
                    }
                    followUserMapper.insertOrUpdate(followUser);
                }
//                List<FollowUser> followUserList = followUserMapper.selectList(Wrappers.query(new FollowUser()).lambda()
//                    .eq(FollowUser::getCustomerId, customer.getCustomerId())
//                    .notIn(FollowUser::getUserId, userIds));
                customerStatsService.refreshCostsByCustomerIds(customer.getCustomerId());
            }
        }
    }

    /**
     * 转让客户
     */
    @Transactional
    @Override
    public void transferCustomer(CustomerTransferBo customerTransferBo) {
        Long out = customerTransferBo.getOut();
        Long in = customerTransferBo.getIn();
        Long customerId = customerTransferBo.getCustomerId();
        Customer customer = baseMapper.selectById(customerId);
        String abstractText = String.format("%s 将 %s 设置为客户 %s 跟进人", userMapper.findNickNameById(out)
            , userMapper.findNickNameById(in), customer.getName());
        if (customer.getEntryType().equals(Customer.EntryTypeFieldEnums.ONE.getValue())) {
            //企微客户只能转让给共享人
            List<FollowUser> followUserList = followUserMapper.selectList(Wrappers.query(new FollowUser()).lambda()
                .eq(FollowUser::getCustomerId, customerId)
                .in(FollowUser::getDelType, Arrays.asList(FollowUser.DelTypeFieldEnums.ZERO.getValue(),
                    FollowUser.DelTypeFieldEnums.ONE.getValue())));
            Map<Long, FollowUser> followUserMap = StreamUtils.toIdentityMap(followUserList, FollowUser::getUserId);
            FollowUser inFollowUser = followUserMap.get(in);
            if (ObjectUtil.isNull(inFollowUser)) {
                throw new ServiceException("接收人与客户非好友关系");
            }
            FollowUser outFollowUser = followUserMap.get(out);
            if (ObjectUtil.isNull(outFollowUser)) {
                throw new ServiceException("您与客户非好友关系");
            }
            if (!outFollowUser.getRelType().equals(FollowUser.RelTypeFieldEnums.ONE.getValue())) {
                throw new ServiceException("您并非该客户的跟进人关系");
            }
            FollowUser shareFollowUser = new FollowUser();
            shareFollowUser.setRelType(FollowUser.RelTypeFieldEnums.TWO.getValue());
            followUserMapper.update(shareFollowUser, Wrappers.query(new FollowUser()).lambda().eq(FollowUser::getCustomerId, customerId));
            FollowUser mainFollowUser = new FollowUser();
            //接收人设置为跟进人
            mainFollowUser.setFollowId(inFollowUser.getFollowId());
            mainFollowUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
            followUserMapper.updateById(mainFollowUser);
        } else {
            //系统客户，
            List<FollowUser> followUserList = followUserMapper.selectList(Wrappers.query(new FollowUser()).lambda()
                .eq(FollowUser::getCustomerId, customerId)
                .in(FollowUser::getDelType, Arrays.asList(FollowUser.DelTypeFieldEnums.ZERO.getValue(),
                    FollowUser.DelTypeFieldEnums.ONE.getValue())));
            Map<Long, FollowUser> followUserMap = StreamUtils.toIdentityMap(followUserList, FollowUser::getUserId);
            FollowUser outFollowUser = followUserMap.get(out);
            if (ObjectUtil.isNull(outFollowUser)) {
                throw new ServiceException("您与客户非好友关系");
            }
            if (!outFollowUser.getRelType().equals(FollowUser.RelTypeFieldEnums.ONE.getValue())) {
                throw new ServiceException("您并非该客户的跟进人关系");
            }
            FollowUser inFollowUser = followUserMap.get(in);
            if (ObjectUtil.isNull(inFollowUser)) {
                //若接收人与客户没有关系则新增关系
                inFollowUser = new FollowUser();
                inFollowUser.setDelType(FollowUser.DelTypeFieldEnums.ZERO.getValue());
                inFollowUser.setCustomerId(customerId);
                inFollowUser.setUserId(in);
                inFollowUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
                inFollowUser.setFollowStage(customer.getFollowStage());
                followUserMapper.insert(inFollowUser);
            }

            FollowUser shareFollowUser = new FollowUser();
            shareFollowUser.setRelType(FollowUser.RelTypeFieldEnums.TWO.getValue());
            followUserMapper.update(shareFollowUser, Wrappers.query(new FollowUser()).lambda().eq(FollowUser::getCustomerId, customerId));
            FollowUser mainFollowUser = new FollowUser();
            //接收人设置为跟进人
            mainFollowUser.setFollowId(inFollowUser.getFollowId());
            mainFollowUser.setRelType(FollowUser.RelTypeFieldEnums.ONE.getValue());
            followUserMapper.updateById(mainFollowUser);
            if (customerTransferBo.getType().equals(CustomerTransferBo.TypeFieldEnums.TWO.getValue())) {
                abstractText = String.format("%s 将客户 %s 转让给 %s", userMapper.findNickNameById(out)
                    , customer.getName(), userMapper.findNickNameById(in));
                //转让（删除转出人与客户关系）
                outFollowUser.setDelType(FollowUser.DelTypeFieldEnums.THREE.getValue());
                outFollowUser.setDelFlag("2");
                followUserMapper.updateById(outFollowUser);
            }
        }
        if (out.equals(in)) {
            throw new ServiceException("转让人与接收人是同一人");
        }
        CustomerLog customerLog = new CustomerLog();
        customerLog.setCustomerId(customer.getCustomerId());
        customerLog.setAbstractText(abstractText);
        customerLogMapper.insert(customerLog);
    }

}
